from django.db import models
from django.contrib.auth.models import User
from django.contrib.contenttypes.models import ContentType
from nokia.reporting.helpers import *
# Create your models here.

class ReportField(models.Model):
    def __str__(self):
        return "ReportField %s" % self.name
    types = models.ManyToManyField(ContentType, verbose_name='Type to report on', \
                                   related_name='reportfields')
    name = models.CharField(maxlength=100, core=True)
    
    @property
    def models(self):
        return [ct.model_class() for ct in self.types.all()]
    
    @property
    def title(self):
        return self.get_reporter_field(self.types.all()[0].model).title

    @property
    def description(self):
        return self.get_reporter_field(self.types.all()[0].model).function.__doc__
        
    def get_reporter_field(self, model):
        """Get the ReporterField that this name applys to given the model"""
        mod = get_model_from_verbose_name(model)
        assert mod in self.models, '%s is not a valid choice of model for this field' % model
        class_reg = getattr(FieldRegister(), mod.__name__)
        return getattr(class_reg, self.name)
        
        
    
    class Admin:
        list_display = ['name',  'title','description']
	list_filter = ['types']

class Report(models.Model):
    def __str__(self):
        return """Report "%s" on type %s, fields: %s""" % (self.title, self.model.__name__, self.fields.count())
    user = models.ForeignKey(User, related_name='reports')
    title = models.CharField(maxlength=50)
    description = models.TextField()
    fields = models.ManyToManyField(ReportField, related_name='reports')
    type = models.ForeignKey(ContentType, verbose_name='Type to report on')
    
    @property
    def model(self):
        return self.type.model_class()

    @property
    def list_display_model(self):
        return self.type.model_class().__name__

    @property
    def field_descriptions(self):
        flds = self.get_report().fields
        return ', '.join([f.title for f in flds])
        
    class Admin:
        list_display = ['title', 'list_display_model', 'user', 'field_descriptions']
        list_filter = ['type']
        search_fields = ['title', 'description']
        js = ['/media/js/report_admin.js']
        
    def get_report(self):
        """Construct and return a Report object using self.fields"""
        register = FieldRegister()
        fields = [f.name for f in self.fields.all()]
        return Reporter(self.model,  register,  *fields)

def possible_fields(type):
    """Given a report's type,  get a list of possible fields"""
    pos_fields = ReportField.objects.filter(types__model=type)
    content_type = ContentType.objects.get(model=type)
    class_reg = getattr(FieldRegister(), content_type.model_class().__name__)
    return [(f.id,  getattr(class_reg, f.name).title) for f in pos_fields]       

    
def generate_fields():
    """Populate the database with fields by looping through all ClassRegisters
    in the FieldRegister. for each field,  check if it's name is in the database
    and if so add the necessary ContentType to the m2m field"""
    from django.db import models
    #Necessary to make sure tt.ticket's reverse relationships are included
    fr = FieldRegister()
    for model in models.get_models():
        #Make sure all of the revrelations and stuff are here
        models.get_app(model.__module__.split('.')[-2])
        ct = ContentType.objects.get_for_model(model)
        class_reg = getattr(fr, model.__name__)
        for fld_name in [k for k, v in class_reg.__dict__.items() if v.__class__ == ReporterField]:
            try:
                field = ReportField.objects.get(name=fld_name)
                field.types.add(ct)
            except ReportField.DoesNotExist, e:
                print fld_name, e
                field = ReportField(name=fld_name)
                field.save() #Can't create a m2m until we have a pk,  so save first
                field.types.add(ct)

        
